package com.example;

import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;

class Channel2{
	public Dictionary<String, Integer> msg;
	public boolean ready;
	public Channel2(){
		msg = new Hashtable<String, Integer>();
		ready = true;
	}
	public synchronized boolean send(Dictionary<String, Integer> dict){
		if(!ready){
			return false;
		}
		Enumeration<String> e = dict.keys();
		while(e.hasMoreElements()){
			String key = e.nextElement();
			Integer val = dict.get(key);
			this.msg.put(key, val);
		}
		ready = false;
		return true;
	}
	public synchronized boolean receive(Channel2 ch){
		if(ready) return false;
		Enumeration<String> e = this.msg.keys();
		while(e.hasMoreElements()){
			String key = e.nextElement();
			Integer val = this.msg.get(key);
			ch.msg.put(key, val);
		}
		ready = true;
		return true;
	}
}
class Begin extends Thread{
	public Channel2 ch_dba;
	public Channel2 ch_sys;
	public Begin(Channel2 ch_dba, Channel2 ch_sys) {this.ch_dba = ch_dba; this.ch_sys = ch_sys;}
	public void run(){
		System.out.println("Entered Begin");
		Dictionary<String, Integer> dict = new Hashtable<String, Integer>();
		dict.put("Begin", 1);
		Dictionary<String, Integer> dict2 = new Hashtable<String, Integer>();
		dict2.put("Begin", 2);
		while(!ch_dba.send(dict)){}
		while(!ch_sys.send(dict2)){}
		System.out.println("Leaving Begin");
	}
}
class Dba_Permission extends Thread{
	public Channel2 ch_begin;
	public Channel2 ch_cleanup;
	public Dba_Permission(Channel2 ch1, Channel2 ch2){ch_begin = ch1 ; ch_cleanup = ch2;}
	public void run(){
		System.out.println("Entered Dba Permission");
		Channel2 msg = new Channel2();
		while(!ch_begin.receive(msg)){}
		Dictionary<String, Integer> dict = new Hashtable<String, Integer>();
		dict.put("dba permission", 1);
		while(!ch_cleanup.send(dict)){}
		System.out.println("Leaving Dba Permission");
	}
}
class System_Permission extends Thread{
	public Channel2 ch_begin;
	public Channel2 ch_cleanup;
	public System_Permission(Channel2 ch1, Channel2 ch2){ch_begin = ch1 ; ch_cleanup = ch2;}
	public void run(){
		System.out.println("Entered System Permission");
		Channel2 msg = new Channel2();
		while(!ch_begin.receive(msg)){}
		Dictionary<String, Integer> dict = new Hashtable<String, Integer>();
		dict.put("system permission", 1);
		while(!ch_cleanup.send(dict)){}
		System.out.println("Leaving System Permission");
	}
}
class Cleanup extends Thread{
	public Channel2 ch_dba;
	public Channel2 ch_sys;
	public Channel2 ch_database;
	public Channel2 ch_system;
	public Cleanup(Channel2 ch_dba, Channel2 ch_sys, Channel2 ch_database, Channel2 ch_system){
		this.ch_dba = ch_dba; this.ch_sys = ch_sys;
		this.ch_database = ch_database;
		this.ch_system = ch_system;
	}
	public void run(){
		System.out.println("Entered Cleanup");
		Channel2 dba = new Channel2();
		Channel2 sys = new Channel2();
		while(!ch_dba.receive(dba)){}
		while(!ch_sys.receive(sys)){}
		Dictionary<String, Integer> dict = new Hashtable<String, Integer>();
		dict.put("cleanup", 1);
		Dictionary<String, Integer> dict2 = new Hashtable<String, Integer>();
		dict2.put("cleanup", 2);
		while(!ch_database.send(dict)){}
		while(!ch_system.send(dict2)){}
		System.out.println("Leaving Cleanup");
	}
}
class DatabaseBackup extends Thread{
	public Channel2 ch_cleanup;
	public Channel2 ch_ready;
	public DatabaseBackup(Channel2 ch1, Channel2 ch2){
		this.ch_cleanup = ch1; this.ch_ready = ch2;
	}
	public void run(){
		System.out.println("Entered Db backup");
		Channel2 cleanup = new Channel2();
		while(!ch_cleanup.receive(cleanup)){}
		Dictionary<String, Integer> dict2 = new Hashtable<String, Integer>();
		dict2.put("Datababse backup", 1);
		while(!ch_ready.send(dict2)){}
		System.out.println("Leaving Db backup");
	}
}
class SystemBackup extends Thread{
	public Channel2 ch_cleanup;
	public Channel2 ch_ready;
	public SystemBackup(Channel2 ch1, Channel2 ch2){
		this.ch_cleanup = ch1; this.ch_ready = ch2;
	}
	public void run(){
		System.out.println("Entered System backup");
		Channel2 cleanup = new Channel2();
		while(!ch_cleanup.receive(cleanup)){}
		Dictionary<String, Integer> dict2 = new Hashtable<String, Integer>();
		dict2.put("System backup", 1);
		while(!ch_ready.send(dict2)){}
		System.out.println("Leaving System backup");
	}
}
class Ready extends Thread{
	public Channel2 ch_database;
	public Channel2 ch_system;
	public Ready(Channel2 ch1, Channel2 ch2){
		this.ch_database = ch1; this.ch_system = ch2;
	}
	public void run(){
		System.out.println("Entered ready");
		Channel2 dba = new Channel2();
		Channel2 sys = new Channel2();
		while(!ch_database.receive(dba)){}
		while(!ch_system.receive(sys)){}
		System.out.println("Leaving ready");
	}
}
public class WorkFlowTest{
	public static void main(String a[]){
		Channel2 c1 = new Channel2(), c2 = new Channel2(), c3 = new Channel2(), c4 = new Channel2(), c5 = new Channel2(), 
				c6 = new Channel2(), c7 = new Channel2(), c8 = new Channel2();
		Begin begin = new Begin(c1, c2);
		Dba_Permission dba_permission = new Dba_Permission(c1, c3);
		System_Permission system_permission = new System_Permission(c2, c4);
		Cleanup cleanup = new Cleanup(c3, c4, c5, c6);
		DatabaseBackup databaseBackup = new DatabaseBackup(c5, c7);
		SystemBackup systembackup = new SystemBackup(c6, c8);
		Ready ready = new Ready(c7, c8);
		ready.start(); databaseBackup.start(); systembackup.start();
		cleanup.start(); system_permission.start(); dba_permission.start(); begin.start();
		
	}
}